package server

import (
	"context"
	"encoding/json"
	"longmen/server/config/global"
	"longmen/server/internal/rpc/games/slot_machine"
	"longmen/server/internal/rpc/tencentim/cache"
	chat2 "longmen/server/internal/rpc/tencentim/chat"
	"longmen/server/internal/rpc/tencentim/config"
	"longmen/server/internal/rpc/tencentim/imsdk"
	"longmen/server/internal/rpc/tencentim/messages"
	room_event2 "longmen/server/internal/rpc/tencentim/room_event"
	"longmen/server/internal/rpc/tencentim/utils"
	"longmen/server/pkg/common/api_models"
	"longmen/server/pkg/db/mysql/models/models_main"
	pb "longmen/server/pkg/protobuf"
	"sync"

	"github.com/spf13/cast"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

var (
	inc         sync.Once
	GamesServer sync.Map
)

func (s *GameServer) Callback(ctx context.Context, req *pb.CallbackReq) (*pb.CallbackResp, error) {
	switch req.GetCallbackCommand() {
	case config.C2CBeforeMsg:
		// 单聊消息
		allMsg := req.GetMsgBody()
		for _, msg := range allMsg {
			switch msg.MsgType {
			case imsdk.TIM_MSG_TYPE_CUSTOM:
				bytes := []byte(msg.MsgContent.Data)
				if len(msg.MsgContent.Data) == 0 {
					bytes = []byte(msg.MsgContent.Text)
				}
				incomeMsg := messages.IncomingMessage{}
				err := json.Unmarshal(bytes, &incomeMsg)
				if err != nil || incomeMsg.Type == nil {
					return utils.CallbackFailResp(nil, "消息不能识别或缺少type"), err
				}
				switch *incomeMsg.Type {
				default:
					return C2CHandler(req, &incomeMsg, bytes)
				}
			default:
				global.Log.Errorf("games Callback error type:%v", msg.MsgType)
			}
		}
	}
	return nil, nil
}

func NewGamesServer() {
	inc.Do(func() {
		GamesServer.Store(GameSlotGameId, slot_machine.NewSlotTable(cast.ToString(GameSlotGameId)))
	})
}

func C2CHandler(req *pb.CallbackReq, m *messages.IncomingMessage, b []byte) (ret *pb.CallbackResp, err error) {
	//global.Log.Debugf("single:%v", req)
	user, err := room_event2.GetUser(req)
	if err != nil {
		iHeader := 0
		if len(req.From_Account) >= 10 {
			iHeader = len(req.From_Account) - 9
		} else {
			cache.SetClientBeforeLogin(req)
			user, err = room_event2.GetUser(req)
		}
		if err != nil {
			user = &chat2.ClientUser{
				Platform:   0,
				UserId:     0,
				RoomId:     m.GroupId,
				Token:      "",
				ClientName: global.Lang.T("anonymous") + req.From_Account[iHeader:len(req.From_Account)], //random.String(5, anonymousNameChars),
				Avatar:     "",
				Level:      0,
				Vip:        0,
				UUID:       "",
				Props:      nil,
				Anonymouse: true,
				Role:       0,
				Permit:     0,
			}
		}
	}
	user.UserId = cast.ToInt(req.From_Account)
	user.RoomId = m.GroupId
	user.OptPlatform = req.GetOptPlatform()
	if user.IP == "" {
		user.IP = req.ClientIP
	}
	if user.Platform == 0 {
		user.Platform = utils.PlatformTrans(req.OptPlatform)
	}
	if user.UserId == m.GroupId {
		user.Role = 2
	}
	game, err := getGame(m.GroupId)
	if err != nil {
		return utils.CallbackOkResp(err.Error()), nil
	}
	switch *m.Type {
	case C2CJoinGame: // 游客进入房间
		game.JoinTable()
	case C2CUserBet: //用户下注
		var buyReq *api_models.UserBetReq
		err = json.Unmarshal(b, &buyReq)
		if err != nil {
			return utils.CallbackFailResp(err.Error(), ""), nil
		}
		game.UserBet(buyReq)
	}
	global.Log.Errorf("[Messages] unsupportted type %s", *m.Type)
	return utils.CallbackOkResp("消息type不能识别"), nil
}

func (s *GameServer) List(ctx context.Context, req *pb.Empty) (*pb.ListResp, error) {
	var games []*pb.Game
	err := global.GetR().Model(&models_main.Game{}).Where("status=1").Order("sort desc").Find(&games).Error
	return &pb.ListResp{
		Games: games,
	}, err
}

func getGame(tableId int) (Table, error) {
	obj, ok := GamesServer.Load(tableId)
	if !ok {
		return nil, status.Error(codes.InvalidArgument, "game not exists")
	}
	table, ok := obj.(Table)
	if !ok {
		return nil, status.Error(codes.InvalidArgument, "game not exists#2")
	}
	return table, nil
}
